package com.lge.remoteshot.camera;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.provider.MediaStore;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.lge.remoteshot.R;
import com.lge.remoteshot.network.ClientManager;
import com.lge.remoteshot.network.ServerManager;
import com.lge.remoteshot.wifidirect.DeviceListFragment;
import com.lge.remoteshot.wifidirect.WiFiDirectBroadcastReceiver;

public class CameraActivity extends Activity implements OnClickListener, OnLongClickListener {
	public static final String TAG = "remoteshotdemo";
	public static final int MSG_ACTION = 1;
	public static final int MSG_PREVIEW = 2;

	public static final int CAMERA_MODE_ORIGINAL = 1;
	public static final int CAMERA_MODE_REMOTE = 2;

	public static final String CAMERA_ACTION_SHOT_STR = "[CAMERA_ACTION_SHOTT]";
	public static final String CAMERA_ACTION_CONTINUAL_SHOT_STR = "[CAMERA_ACTION_CSHOT]";
	public static final String CAMERA_ACTION_TIMER_SHOT_STR = "[CAMERA_ACTION_TSHOT]";
	public static final String CAMERA_ACTION_FLASH_STR = "[CAMERA_ACTION_FLASH]";
	public static final String CAMERA_ACTION_FOCUS_STR = "[CAMERA_ACTION_FOCUS]";
	public static final String CAMERA_ACTION_BACK_STR = "[CAMERA_ACTION_BACKK]";

	private int mode;

	private WifiP2pManager manager;
	private final IntentFilter intentFilter = new IntentFilter();
	private Channel channel;

	private BroadcastReceiver receiver = null;

	private ClientManager clientManager;
	private ServerManager serverManager;

	private CameraSurfaceView surfaceView;

	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case MSG_ACTION:
				if (((String) msg.obj).equals(CAMERA_ACTION_FLASH_STR)) {
					// debug
					// Toast.makeText(getApplicationContext(),
					// "CAMERA_ACTION_FLASH",
					// Toast.LENGTH_SHORT).show();
					Parameters param = surfaceView.getCamera().getParameters();

					if (param.getFlashMode().equals(Parameters.FLASH_MODE_OFF)) {
						param.setFlashMode(Parameters.FLASH_MODE_ON);
						surfaceView.getCamera().setParameters(param);
						((ImageButton) findViewById(R.id.camera_flash_btn))
								.setImageResource(R.drawable.icon_flash_on);
					} else {
						param.setFlashMode(Parameters.FLASH_MODE_OFF);
						surfaceView.getCamera().setParameters(param);
						((ImageButton) findViewById(R.id.camera_flash_btn))
								.setImageResource(R.drawable.icon_flash_off);
					}
				} else if (((String) msg.obj).equals(CAMERA_ACTION_FOCUS_STR)) {
					// debug
					// Toast.makeText(getApplicationContext(),
					// "CAMERA_ACTION_FOCUS",
					// Toast.LENGTH_SHORT).show();
					surfaceView.getCamera().autoFocus(mAutoFocus);
				} else if (((String) msg.obj).equals(CAMERA_ACTION_SHOT_STR)) {
					// debug
					// Toast.makeText(getApplicationContext(),
					// "CAMERA_ACTION_SHOT",
					// Toast.LENGTH_SHORT).show();
					surfaceView.getCamera().takePicture(null, null, mPicture);
				} else if (((String) msg.obj).equals(CAMERA_ACTION_CONTINUAL_SHOT_STR)) {
					// debug
					// Toast.makeText(getApplicationContext(),
					// "CAMERA_ACTION_CONTINUAL_SHOT",
					// Toast.LENGTH_SHORT).show();
					ContinualShotHandler csHandler = new ContinualShotHandler();
					csHandler.sendEmptyMessageDelayed(0, 0);
					csHandler.sendEmptyMessageDelayed(0, 2000);
					csHandler.sendEmptyMessageDelayed(0, 4000);
				} else if (((String) msg.obj).equals(CAMERA_ACTION_TIMER_SHOT_STR)) {
					ContinualShotHandler csHandler = new ContinualShotHandler();
					csHandler.sendEmptyMessageDelayed(0, 2500);

					FlashHandler fHandler = new FlashHandler();
					fHandler.sendEmptyMessageDelayed(0, 1000);
					fHandler.sendEmptyMessageAtTime(0, 2000);

				} else if (((String) msg.obj).equals(CAMERA_ACTION_BACK_STR)) {
					// debug
					// Toast.makeText(getApplicationContext(),
					// "CAMERA_ACTION_BACK",
					// Toast.LENGTH_SHORT).show();
					onBackPressed();
				}
				break;
			case MSG_PREVIEW:
				surfaceView.setReceiveFrame((byte[]) msg.obj);
				break;
			}
		};
	};

	class ContinualShotHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			surfaceView.getCamera().takePicture(null, null, mPicture);
		}
	}
	
	class FlashHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			Parameters param = surfaceView.getCamera().getParameters();
			String originMode = param.getFlashMode();

			param.setFlashMode(Parameters.FLASH_MODE_TORCH);
			surfaceView.getCamera().setParameters(param);
			
			param.setFlashMode(originMode);
			surfaceView.getCamera().setParameters(param);
		}
	}

	AutoFocusCallback mAutoFocus = new AutoFocusCallback() {
		public void onAutoFocus(boolean success, Camera camera) {
			// mShutter.setEnabled(success);
		}
	};
	PictureCallback mPicture = new PictureCallback() {
		public void onPictureTaken(final byte[] data, Camera camera) {
			handler.post(new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub
					File mediaStorageDir = new File(Environment
							.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
							"RemoteShot");
					if (!mediaStorageDir.exists()) {
						if (!mediaStorageDir.mkdir()) {
							Log.d(TAG, "failed to create directory.");
							return;
						}
					}
					String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
					File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"
							+ timeStamp + ".jpg");
					Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
					Uri uri = Uri.fromFile(mediaFile);
					intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
					intent.setData(uri);
					sendBroadcast(intent);

					try {
						FileOutputStream fos = new FileOutputStream(mediaFile);
						fos.write(data);
						fos.flush();
						fos.close();
					} catch (Exception e) {
						Toast.makeText(CameraActivity.this,
								"occur error while saving image : " + e.getMessage(), 0).show();
						return;
					}
					Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
					scanIntent.setData(uri);
					sendBroadcast(scanIntent);

					Toast.makeText(CameraActivity.this, "save image completely : " + uri.getPath(),
							0).show();

					surfaceView.getCamera().startPreview();
				}
			});
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.camera_layout);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		Intent intent = getIntent();
		if (intent != null) {
			mode = intent.getExtras().getInt("mode");
			initSurfaceView(mode);
			initCameraMode(mode);
		}

		intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

		manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
		channel = manager.initialize(this, getMainLooper(), null);
		DeviceListFragment fragment = ((DeviceListFragment) getFragmentManager().findFragmentById(
				R.id.frag_list));
		fragment.setWiFiP2PManager(manager);
		fragment.setChannel(channel);

		((ImageButton) findViewById(R.id.camera_flash_btn)).setOnClickListener(this);
		((ImageButton) findViewById(R.id.camera_shot_btn)).setOnClickListener(this);
		// ((ImageButton)
		// findViewById(R.id.camera_gallery_btn)).setOnClickListener(this);
		((ImageButton) findViewById(R.id.camera_shot_btn)).setOnLongClickListener(this);
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
		registerReceiver(receiver, intentFilter);
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		unregisterReceiver(receiver);
		((DeviceListFragment) getFragmentManager().findFragmentById(R.id.frag_list)).disconnect();
		if (serverManager != null)
			serverManager.closeServerManager();
		if (clientManager != null)
			clientManager.closeClientManager();

		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		PowerManager.WakeLock wi = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "My_tag");
		wi.acquire();
		wi.release();
		
		onBackPressed();
		super.onPause();
	}

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		if (mode == CAMERA_MODE_REMOTE) {
			if (serverManager != null)
				serverManager.sendAction(CAMERA_ACTION_BACK_STR);
		} else if (mode == CAMERA_MODE_ORIGINAL) {
			if (clientManager != null)
				clientManager.sendAction(CAMERA_ACTION_BACK_STR);
		}
		finish();
	}

	@Override
	protected void onNewIntent(Intent intent) {
		// TODO Auto-generated method stub
		super.onNewIntent(intent);
		setIntent(intent);
	}

	public int getMode() {
		return this.mode;
	}

	public void startServer(WifiP2pInfo info) {
		((DeviceListFragment) getFragmentManager().findFragmentById(R.id.frag_list))
				.setVisibility(View.INVISIBLE);
		serverManager = new ServerManager(this);
	}

	public void startClient(String address) {
		((DeviceListFragment) getFragmentManager().findFragmentById(R.id.frag_list))
				.setVisibility(View.INVISIBLE);
		clientManager = new ClientManager(this, address);
		surfaceView.setClientManager(clientManager);
		Log.d(CameraActivity.TAG, "CameraActivity:startClient:isStarted");
	}

	public void setShowRemoteStateMessage() {
		((TextView) findViewById(R.id.camera_state)).setText("원격 제어 중입니다.");
		((TextView) findViewById(R.id.camera_state)).setVisibility(View.VISIBLE);
	}

	public void stopServer() {
		if (serverManager != null)
			serverManager.closeServerManager();
		serverManager = null;
	}

	public void stopClient() {
		if (clientManager != null)
			clientManager.closeClientManager();
		clientManager = null;
	}

	public void setReceivedAction(String action) {
		Message msg = Message.obtain();
		msg.what = MSG_ACTION;
		msg.obj = action;
		handler.sendMessage(msg);
	}

	public void setReceiveFrame(byte[] data) {
		Message msg = Message.obtain();
		msg.what = MSG_PREVIEW;
		msg.obj = data;
		handler.sendMessage(msg);
	}

	@Override
	public void onClick(View v) {
		if (mode != CAMERA_MODE_REMOTE) {
			return;
		}

		int id = v.getId();
		switch (id) {
		case R.id.camera_shot_btn:
			if (((String) v.getTag()).equals("normal_mode")) {
				serverManager.sendAction(CAMERA_ACTION_SHOT_STR);
			} else if (((String) v.getTag()).equals("continual_mode")) {
				serverManager.sendAction(CAMERA_ACTION_CONTINUAL_SHOT_STR);
			} else {
				serverManager.sendAction(CAMERA_ACTION_TIMER_SHOT_STR);
			}
			break;
		case R.id.camera_flash_btn:
			// debug network
			serverManager.sendAction(CAMERA_ACTION_FLASH_STR);
			String flashState = (String) ((ImageButton) findViewById(R.id.camera_flash_btn))
					.getTag();
			if (flashState.equals("off")) {
				((ImageButton) findViewById(R.id.camera_flash_btn)).setTag("on");
				((ImageButton) findViewById(R.id.camera_flash_btn))
						.setImageResource(R.drawable.icon_flash_on);
			} else {
				((ImageButton) findViewById(R.id.camera_flash_btn)).setTag("off");
				((ImageButton) findViewById(R.id.camera_flash_btn))
						.setImageResource(R.drawable.icon_flash_off);
			}
			break;
		case R.id.camera_gallery_btn:
			break;
		}
	}

	@Override
	public boolean onLongClick(View v) {
		Log.d(CameraActivity.TAG, "shutter onLongClick");
		if (mode != CAMERA_MODE_REMOTE) {
			return false;
		}

		int id = v.getId();
		if (id != R.id.camera_shot_btn) {
			return false;
		}

		// So now, We can know that View-v is the shutter button.
		if (((String) v.getTag()).equals("normal_mode")) {
			// (TODO) Have to change R.drawable.icon_flash_on to timer icon.
			((ImageButton) v).setImageResource(R.drawable.shutter_timer);
			v.setTag("timer_mode");
		} else if (((String) v.getTag()).equals("timer_mode")) {
			((ImageButton) v).setImageResource(R.drawable.shutter_continue);
			v.setTag("continual_mode");
		} else {
			((ImageButton) v).setImageResource(R.drawable.shutter);
			v.setTag("normal_mode");
		}

		return true;
	}

	private void initCameraMode(int mode) {
		if (mode == CAMERA_MODE_ORIGINAL) {
			((ImageButton) findViewById(R.id.camera_flash_btn)).setEnabled(false);
			((ImageButton) findViewById(R.id.camera_gallery_btn)).setEnabled(false);
			((ImageButton) findViewById(R.id.camera_shot_btn)).setEnabled(false);
		} else if (mode == CAMERA_MODE_REMOTE) {
			((ImageButton) findViewById(R.id.camera_flash_btn)).setEnabled(true);
			((ImageButton) findViewById(R.id.camera_gallery_btn)).setEnabled(true);
			((ImageButton) findViewById(R.id.camera_shot_btn)).setEnabled(true);
		}
	}

	private void initSurfaceView(int mode) {
		surfaceView = ((CameraSurfaceView) findViewById(R.id.camera_preview));
		surfaceView.setMode(mode);
		surfaceView.init();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		if (event.getAction() == MotionEvent.ACTION_UP) {
			if (mode == CAMERA_MODE_REMOTE) {
				if (serverManager != null)
					serverManager.sendAction(CAMERA_ACTION_FOCUS_STR);
			}
		}
		return true;
	}

}
/* end of file */
